package com.sinux.generality.provider.pay.controller;

import com.alibaba.fastjson.JSONObject;

import com.sinux.generality.basesupport.utils.tool.ServiceUtil;
import com.sinux.generality.provider.pay.config.WeChatPayConfigure;
import com.sinux.generality.provider.pay.factory.enums.NotifyTypeEnums;
import com.sinux.generality.provider.pay.notify.PayNotifyBench;
import com.sinux.generality.provider.pay.notify.RefundNotifyHandle;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.crypto.BadPaddingException;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;

/****
 * @className WxCallBackController
 * @describe 支付回调接口
 * @author lhz
 * @date 2021/10/09 10:46
 * @version 0.0.1
 */

@RestController
@RequestMapping("/wxpay/callback")
public class WxCallBackController {

    private final static Logger LOGGER = LoggerFactory.getLogger("WxCallBackController.class");
    @Resource
    private ServiceUtil serviceUtil;
    @Resource
    private PayNotifyBench payNotifyBench;
    @Resource
    private RefundNotifyHandle refundNotifyHandle;

    /**
     * combineNotify 支付回调
     * @author lhz
     * @param request
     * @return Map<String,Object>
     */
    @RequestMapping(value = "/notify")
    public Map<String, Object> combineNotify(HttpServletRequest request) {

        // 创建支付应答对象
        Map<String, Object> map = new HashMap<>(2);
        InputStream inStream;
        String messageId = "";
        String resourceRes = "";
        String result = "";
        String code="";
        try {
            inStream = request.getInputStream();

            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            outSteam.close();
            inStream.close();
            // 获取微信调用我们notify_url的返回信息
            result = new String(outSteam.toByteArray(), StandardCharsets.UTF_8);
            JSONObject json = JSONObject.parseObject(result);
            //通知类型
            String eventType = (String) json.get("event_type");
            //通知数据 加密信息
            JSONObject resource = json.getJSONObject("resource");
            //解密信息
            AesUtil aesUtil = new AesUtil(WeChatPayConfigure.apiV3key.getBytes(StandardCharsets.UTF_8));
            //解析后的数据
            resourceRes = aesUtil.decryptToString(
                    resource.getString("associated_data").getBytes(StandardCharsets.UTF_8),
                    resource.getString("nonce").getBytes(StandardCharsets.UTF_8), resource.getString("ciphertext"));
            messageId = json.getString("id");
            //记录消息通知，如果存在直接并处理成功的业务直接返回
            //处理回调通知
            if (eventType.equals(NotifyTypeEnums.TRANSACTION_SUCCESS.getCode())){
                payNotifyBench.notifyHandle(resourceRes);
            }else if (eventType.equals(NotifyTypeEnums.REFUND_SUCCESS.getCode())){
                refundNotifyHandle.notifyHandle(resourceRes);
            }
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            return map;
        } catch (IOException e) {
            LOGGER.error("回调通知io异常信息：【{}】 异常信息：", request, e);
        } catch (BadPaddingException e) {

            LOGGER.error("回调通知加密数据：【{}】 异常信息：", result, e);
        } catch (GeneralSecurityException e) {
            LOGGER.error("解密失败：【{}】 异常信息：", result, e);
        }
        map.put("code", "FAIL");
        map.put("message", "系统错误");
        return map;
    }

}